home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / bash / bash_108 / bash-108.zoo / bash-1.08 / ulimit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-17  |  9.7 KB  |  450 lines

  1. /* ulimit.c -- Setting resource usage for children of the shell. */
  2.  
  3. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU Bash, the Bourne Again SHell.
  6.  
  7. Bash is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 1, or (at your option) any later
  10. version.
  11.  
  12. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with Bash; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include <sys/types.h>
  23. #include <sys/param.h>
  24. #include <errno.h>
  25. #include "shell.h"
  26.  
  27. extern int errno;
  28.  
  29. #if defined (HAVE_RESOURCE)
  30. #include <sys/time.h>
  31. #include <sys/resource.h>
  32. #else
  33. #include <sys/times.h>
  34. #endif
  35.  
  36. #if defined (_POSIX_VERSION)
  37. #include <limits.h>
  38. #endif
  39.  
  40. /* Check for the most basic synbols.  If they aren't present, this
  41.    system's <sys/resource.h> isn't very useful to us. */
  42. #if !defined RLIMIT_FSIZE
  43. #  undef HAVE_RESOURCE
  44. #endif
  45.  
  46. /* **************************************************************** */
  47. /*                                    */
  48. /*            Ulimit builtin and Hacks.               */
  49. /*                                    */
  50. /* **************************************************************** */
  51.  
  52. /* Block size for ulimit operations. */
  53. #define ULIMIT_BLOCK_SIZE ((long)1024)
  54.  
  55. #define u_FILE_SIZE 1
  56. #define u_MAX_BREAK_VAL 3
  57. #define u_PIPE_SIZE 4
  58. #define u_CORE_FILE_SIZE 6
  59. #define u_DATA_SEG_SIZE 8
  60. #define u_PHYS_MEM_SIZE 10
  61. #define u_CPU_TIME_LIMIT 12
  62. #define u_STACK_SIZE 14
  63. #define u_NUM_OPEN_FILES 16
  64.  
  65. #ifndef RLIM_INFINITY
  66. #define RLIM_INFINITY  0x7fffffff
  67. #endif
  68.  
  69. static long pipesize ();
  70.  
  71. /* Report or set limits associated with certain per-process resources.
  72.    See the help documentation in builtins.c for a full description.
  73.    Chet Ramey & Brian Fox 3/13/89. */
  74. ulimit_builtin (list)
  75.      register WORD_LIST *list;
  76. {
  77.   long shell_ulimit ();
  78.   register char *s;
  79.   int c, setting, cmd, r = EXECUTION_SUCCESS;
  80.   long current_limit, real_limit, limit = -1L;
  81.   long block_factor;
  82.  
  83.   do
  84.     {
  85.       cmd = u_FILE_SIZE;
  86.       setting = 0;
  87.       block_factor = ULIMIT_BLOCK_SIZE;
  88.  
  89.       if (list)
  90.     {
  91.       s = list->word->word;
  92.       if (s && (*s == '-'))
  93.         {
  94.           c = *++s;
  95.  
  96.           if (!c || *++s)
  97.         goto error_case;
  98.  
  99.           list = list->next;
  100.  
  101.           switch (c)
  102.         {
  103.         case 'f':
  104.           cmd = u_FILE_SIZE;
  105.           break;
  106.  
  107. #if defined (HAVE_RESOURCE)
  108.         case 'a':
  109.           print_all_limits ();
  110.           return (EXECUTION_SUCCESS);
  111.  
  112.         case 'c': cmd = u_CORE_FILE_SIZE;
  113.           break;
  114.  
  115.         case 'd': cmd = u_DATA_SEG_SIZE;
  116.           break;
  117.  
  118.         case 'm': cmd = u_PHYS_MEM_SIZE;
  119.           break;
  120.  
  121.         case 't':
  122.           cmd = u_CPU_TIME_LIMIT;
  123.           block_factor = 1;    /* seconds */
  124.           break;
  125.  
  126.         case 's':
  127.           cmd = u_STACK_SIZE;
  128.           break;
  129.  
  130.         case 'p':
  131.           cmd = u_PIPE_SIZE;
  132.           block_factor = 512;
  133.           break;
  134.  
  135.         case 'n':
  136.           cmd = u_NUM_OPEN_FILES;
  137.           block_factor = 1;
  138.           break;
  139.  
  140. #endif /* HAVE_RESOURCE */
  141.         default:
  142.         error_case:
  143. #if ! defined (HAVE_RESOURCE)
  144.           builtin_error("usage: ulimit [-f] [new limit]");
  145. #else
  146.           builtin_error("usage: ulimit [-acmdstfpn] [new limit]");
  147. #endif
  148.           return EXECUTION_FAILURE;
  149.         }
  150.         }
  151.       
  152.       /* If an argument was supplied for the command, then we want to
  153.          set the limit. */
  154.       if (list)
  155.         {
  156.           s = list->word->word;
  157.           list = list->next;
  158.           if (sscanf (s, "%ld", &limit) != 1)
  159.         {
  160.           if (strcmp (s, "unlimited") == 0)
  161.             limit = RLIM_INFINITY;
  162.           else
  163.             {
  164.               builtin_error ("bad non-numeric arg `%s'", s);
  165.               return (EXECUTION_FAILURE);
  166.             }
  167.         }
  168.           setting++;
  169.         }
  170.     }
  171.  
  172.       if (limit == RLIM_INFINITY)
  173.     block_factor = 1;
  174.  
  175.       real_limit = limit * block_factor;
  176.  
  177.       current_limit = shell_ulimit (cmd, real_limit, 0);
  178.  
  179.       if (setting)
  180.     {
  181. #if !defined (HAVE_RESOURCE)
  182.       if ((current_limit < (real_limit)) && (getuid() != 0))
  183.         {
  184.           builtin_error ("cannot raise limit");
  185.           return (EXECUTION_FAILURE);
  186.         }
  187. #endif
  188.  
  189.         if (shell_ulimit (cmd, real_limit, 1) == -1)
  190.           {
  191.         builtin_error ("cannot raise limit: %s", strerror(errno));
  192.         r = EXECUTION_FAILURE;
  193.           }
  194.         else
  195.           r = EXECUTION_SUCCESS;
  196.  
  197.         return (r);
  198.     }
  199.       else
  200.     {
  201.       if (current_limit != RLIM_INFINITY)
  202.         printf ("%ld\n", (current_limit / block_factor));
  203.       else
  204.         printf ("unlimited\n");
  205.     }
  206.     }
  207.   while (list);
  208.  
  209.   return (EXECUTION_SUCCESS);
  210. }
  211.  
  212. /* The ulimit that we call from within Bash.  Extended to handle
  213.    more resources by Chet Ramey (chet@cwjcc.cwru.edu).
  214.    WHICH says which limit to twiddle; SETTING is non-zero if NEWLIM
  215.    contains the desired new limit.  Otherwise, the existing limit is
  216.    returned. */
  217. long
  218. shell_ulimit (which, newlim, setting)
  219.      int which, setting;
  220.      long newlim;
  221. {
  222. #if defined (HAVE_RESOURCE)
  223.   struct rlimit limit;
  224. #endif
  225.  
  226.   switch (which)
  227.     {
  228.  
  229.     case u_FILE_SIZE:
  230.       if (!setting)
  231.     {
  232. #if !defined (HAVE_RESOURCE)
  233.       /* ulimit () returns a number that is in 512 byte blocks, thus  we
  234.          must multiply it by 512 to get back to bytes.  This is false
  235.          only under HP/UX 6.x. */
  236.       long result;
  237.  
  238.       result = ulimit (1, 0l);
  239.  
  240. #if defined (hpux) && !defined (_POSIX_VERSION)
  241.       return (result);
  242. #else
  243.       return (result * 512);
  244. #endif /* Hpux 6.x */
  245. #else
  246.       if (getrlimit (RLIMIT_FSIZE, &limit) != 0)
  247.         return ((long) -1);
  248.       return (limit.rlim_cur);
  249. #endif
  250.     }
  251.       else
  252.     {
  253. #if !defined (HAVE_RESOURCE)
  254.       return (ulimit (2, newlim / 512L));
  255. #else
  256.       getrlimit (RLIMIT_FSIZE, &limit);
  257.       limit.rlim_cur = newlim;
  258.       return (setrlimit (RLIMIT_FSIZE, &limit));
  259. #endif
  260.     }
  261.  
  262.     case u_MAX_BREAK_VAL:
  263. #if !defined (HAVE_RESOURCE)
  264.       if (!setting)
  265.     return (ulimit (3, 0L));
  266.       else
  267.     return ((long) -1);
  268. #else
  269.       if (!setting)
  270.     {
  271.       if (getrlimit (RLIMIT_DATA, &limit) != 0)
  272.         return ((long) -1);
  273.           return (limit.rlim_cur);
  274.     }
  275.       else
  276.     {
  277.       getrlimit (RLIMIT_DATA, &limit);
  278.       limit.rlim_cur = newlim;
  279.       return (setrlimit (RLIMIT_DATA, &limit));
  280.     }
  281. #endif
  282.  
  283. #if defined (HAVE_RESOURCE)
  284.       /* You can't get or set the pipe size with getrlimit, so we have to
  285.          cheat.  */
  286.     case u_PIPE_SIZE:
  287.       if (setting)
  288.     {
  289.       errno = EINVAL;
  290.       return ((long) -1);
  291.     }
  292.       return (pipesize ());
  293.  
  294.     case u_CORE_FILE_SIZE:
  295.       if (!setting)
  296.     {
  297.       if (getrlimit (RLIMIT_CORE, &limit) != 0)
  298.         return ((long) -1);
  299.       return (limit.rlim_cur);
  300.     }
  301.       else
  302.     {
  303.       getrlimit (RLIMIT_CORE, &limit);
  304.       limit.rlim_cur = newlim;
  305.       return (setrlimit (RLIMIT_CORE, &limit));
  306.     }
  307.  
  308.     case u_DATA_SEG_SIZE:
  309.       if (!setting)
  310.     {
  311.       if (getrlimit (RLIMIT_DATA, &limit) != 0)
  312.         return (long) -1;
  313.       return (limit.rlim_cur);
  314.     }
  315.       else
  316.     {
  317.       getrlimit (RLIMIT_DATA, &limit);
  318.       limit.rlim_cur = newlim;
  319.       return (setrlimit (RLIMIT_DATA, &limit));
  320.     }
  321.  
  322.     case u_PHYS_MEM_SIZE:
  323.       if (!setting)
  324.     {
  325.       if (getrlimit (RLIMIT_RSS, &limit) != 0)
  326.         return ((long) -1);
  327.       return (limit.rlim_cur);
  328.     }
  329.       else
  330.     {
  331.       getrlimit (RLIMIT_RSS, &limit);
  332.       limit.rlim_cur = newlim;
  333.       return (setrlimit (RLIMIT_RSS, &limit));
  334.     }
  335.  
  336.     case u_CPU_TIME_LIMIT:
  337.       if (!setting)
  338.     {
  339.       if (getrlimit (RLIMIT_CPU, &limit) != 0)
  340.         return ((long) -1);
  341.       return (limit.rlim_cur);
  342.     }
  343.       else
  344.     {
  345.       getrlimit (RLIMIT_CPU, &limit);
  346.       limit.rlim_cur = newlim;
  347.       return (setrlimit (RLIMIT_CPU, &limit));
  348.     }
  349.  
  350.     case u_STACK_SIZE:
  351.       if (!setting)
  352.     {
  353.       if (getrlimit (RLIMIT_STACK, &limit) != 0)
  354.         return ((long) -1);
  355.       return (limit.rlim_cur);
  356.     }
  357.       else
  358.     {
  359.       getrlimit (RLIMIT_STACK, &limit);
  360.       limit.rlim_cur = newlim;
  361.       return (setrlimit (RLIMIT_STACK, &limit));
  362.     }
  363.  
  364.     case u_NUM_OPEN_FILES:
  365.       if (setting)
  366.     {
  367. #if defined (RLIMIT_NOFILE)
  368.       getrlimit (RLIMIT_NOFILE, &limit);
  369.       limit.rlim_cur = newlim;
  370.       return (setrlimit (RLIMIT_NOFILE, &limit));
  371. #else /* !RLIMIT_NOFILE */
  372.       errno = EINVAL;
  373.       return ((long) -1);
  374. #endif /* !RLIMIT_NOFILE */
  375.     }
  376.       else
  377.     return ((long) getdtablesize ());
  378.  
  379. #endif /* HAVE_RESOURCE */
  380.  
  381.     default:
  382.       errno = EINVAL;
  383.       return ((long) -1);
  384.     }
  385. }
  386.  
  387. #include "pipesize.h"
  388.  
  389. static long
  390. pipesize ()
  391. {
  392. #if defined (PIPE_BUF)
  393.       /* This is defined on Posix systems. */
  394.       return ((long) PIPE_BUF);
  395. #else
  396. #  if defined (PIPESIZE)
  397.       /* This is defined by running a program from the Makefile. */
  398.       return ((long) PIPESIZE);
  399. #  else
  400.  
  401.       errno = EINVAL;
  402.       return ((long) -1);
  403. #  endif /* PIPESIZE */
  404. #endif /* PIPE_BUF */
  405. }
  406.  
  407. #if defined (HAVE_RESOURCE)
  408.  
  409. #if !defined (RLIM_NLIMITS)
  410. #define RLIM_NLIMITS 6        /* Number of resource limits. */
  411. #endif
  412.  
  413. typedef struct {
  414.   int  parameter;        /* Parameter to pass to getrlimit (). */
  415.   int  block_factor;        /* Blocking factor for specific limit. */
  416.   char *description;        /* Descriptive string to output. */
  417. } BSD_RESOURCE_LIMITS;
  418.  
  419. BSD_RESOURCE_LIMITS limits[RLIM_NLIMITS + 1] = {
  420.   { RLIMIT_CPU,      1, "cpu time (seconds)" },
  421.   { RLIMIT_RSS,   1024, "max memory size (kbytes)" },
  422.   { RLIMIT_DATA,  1024, "data seg size (kbytes)" },
  423.   { RLIMIT_STACK, 1024, "stack size (kbytes)" },
  424.   { RLIMIT_FSIZE, 1024, "file size (blocks)" },
  425.   { RLIMIT_CORE,  1024, "core file size (blocks)" },
  426.   { 0, 0, (char *)NULL }
  427. };
  428.  
  429. print_all_limits ()
  430. {
  431.   register int i;
  432.   struct rlimit rl;
  433.   long limit;
  434.  
  435.   for (i = 0; i < RLIM_NLIMITS && limits[i].description; i++)
  436.     {
  437.       getrlimit (limits[i].parameter, &rl);
  438.       limit = rl.rlim_cur;
  439.       printf ("%-25s", limits[i].description);
  440.       if (limit == RLIM_INFINITY)
  441.     printf ("unlimited\n");
  442.       else
  443.     printf ("%ld\n", limit / limits[i].block_factor);
  444.     }
  445.   printf ("%-25s%ld\n", "pipe size (512 bytes)", (pipesize () / 512));
  446.   printf ("%-25s%ld\n", "open files", getdtablesize ());
  447. }
  448.  
  449. #endif /* HAVE_RESOURCE */
  450.